package cn.demomaster.quickpermission;

import android.Manifest;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.Application;
import android.content.ActivityNotFoundException;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.accessibility.AccessibilityManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.demomaster.quickpermission.listener.IPermissionHandler;

import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;

/**
 * 系统权限管理
 * Created by huan on 2017/11/14.
 */
public class QuickPermission2 {
    public static final String TAG = "PermissionManager";
    public static final int REQUEST_PERMISS_COMMON_CODE = 32418;
    //请求悬浮
    public static final int REQUEST_PERMISS_SPECIAL_CODE = 32419;
    IPermissionHandler permissionHandler;
    public static WeakReference<Activity> activityWeakReference;
    private static QuickPermission2 instance;

    public static QuickPermission2 getInstance() {
        if (instance == null) {
            instance = new QuickPermission2();
        }
        return instance;
    }

    private QuickPermission2() {
        this.permissionHandler = new PermissionHandler();
    }

    public void init(Application application) {
        application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
                activityWeakReference = new WeakReference<>(activity);
            }

            @Override
            public void onActivityStarted(@NonNull Activity activity) {
                activityWeakReference = new WeakReference<>(activity);
            }

            @Override
            public void onActivityResumed(@NonNull Activity activity) {
                activityWeakReference = new WeakReference<>(activity);
            }

            @Override
            public void onActivityPaused(@NonNull Activity activity) {

            }

            @Override
            public void onActivityStopped(@NonNull Activity activity) {

            }

            @Override
            public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {

            }

            @Override
            public void onActivityDestroyed(@NonNull Activity activity) {

            }
        });
    }

    public static PermissionRequest with() {
        return new PermissionRequest();
    }

    //跳转到设置-请求悬浮窗权限
    @TargetApi(Build.VERSION_CODES.M)
    public static void requestOverlayPermission(Activity context, Class<? extends Activity> guidActivityClass) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        intent.setData(Uri.parse("package:" + context.getPackageName()));
        //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivityForResult(intent, REQUEST_PERMISS_SPECIAL_CODE);
    }

    // 跳转到设置-允许安装未知来源-页面
    @TargetApi(Build.VERSION_CODES.O)
    public static void startInstallPermissionSettingActivity(final Context context) {
        Uri packageURI = Uri.parse("package:" + context.getPackageName());
        //注意这个是8.0新API
        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
        ((Activity) context).startActivityForResult(intent, REQUEST_PERMISS_SPECIAL_CODE);
        //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //context.startActivity(intent);//startActivityForResult
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static boolean isGrantedUsagePremission(Context context) {
        AppOpsManager appOps = (AppOpsManager) context
                .getSystemService(Context.APP_OPS_SERVICE);
        int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
                android.os.Process.myUid(), context.getPackageName());
        if (mode == AppOpsManager.MODE_DEFAULT) {
            return (context.checkCallingOrSelfPermission(
                    Manifest.permission.PACKAGE_USAGE_STATS)
                    == PackageManager.PERMISSION_GRANTED);
        } else {
            return (mode == AppOpsManager.MODE_ALLOWED);
        }
    }

    /**
     * 在manifest中是否已经注册
     *
     * @param context
     * @param permissionName
     * @return
     */
    private static boolean isInAndroidManifest(Context context, String permissionName) {
        if (permissionName.equals(Manifest.permission.BIND_ACCESSIBILITY_SERVICE)) {
            return true;
        }
        PackageManager pm = context.getPackageManager();
        PackageInfo pack = null;
        try {
            pack = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
            String[] permissionStrings = pack.requestedPermissions;
            if (permissionStrings != null) {
                for (String str : permissionStrings) {
                    //Log.e(TAG, "permissionName:" + str+","+permissionName);
                    if (str.equalsIgnoreCase(permissionName)) {
                        return true;
                    }
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }
    public static boolean checkPermission(List<String> permissions) {
        return checkPermission(activityWeakReference.get(), permissions.toArray(new String[permissions.size()]));
    }
    public static boolean checkPermission(String... permissions) {
        return checkPermission(activityWeakReference.get(), permissions);
    }

    public static boolean checkPermission(Context context, String... permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }
        for (String permission : permissions) {
            if (!checkPermission2(permission)) {
                return false;
            }
        }
        return true;
    }

    private static boolean checkPermission2(String permissionName) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {// 当手机系统大于 23 时，才有必要去判断权限是否获取
            return true;
        }
        boolean isRegisted = isInAndroidManifest(activityWeakReference.get(), permissionName);
        if (!isRegisted) {
            Log.e(TAG, "[" + permissionName + "]权限未在AndroidManifest注册");
            return false;
        }
        switch (permissionName) {
            case Manifest.permission.REQUEST_INSTALL_PACKAGES:
            case Manifest.permission.INSTALL_PACKAGES:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    return activityWeakReference.get().getPackageManager().canRequestPackageInstalls();
                }
                break;
            case Manifest.permission.SYSTEM_ALERT_WINDOW:
                return Settings.canDrawOverlays(activityWeakReference.get());
            case Manifest.permission.PACKAGE_USAGE_STATS:
                return isGrantedUsagePremission(activityWeakReference.get());
            case Manifest.permission.WRITE_SETTINGS:
            case Manifest.permission.WRITE_SECURE_SETTINGS:
                return Settings.System.canWrite(activityWeakReference.get());
            case Manifest.permission.BIND_ACCESSIBILITY_SERVICE:
                return checkAndEnableAccessibilityService(activityWeakReference.get());
            case Manifest.permission.MANAGE_EXTERNAL_STORAGE:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    //boolean hasAnyRequestedLegacyExternalStorage =
                        /*PackageManager pm = context.getPackageManager();
                        PackageInfo packageInfo = pm.getPackageArchiveInfo("",0);
                        context.getApplicationContext().getApplicationInfo().hasRequestedLegacyExternalStorage();*/
                    //context.getApplicationContext()..getApplicationInfo(). requestLegacyExternalStorage
                    boolean p = Environment.isExternalStorageManager();
                    return p;// 权限是否已经 授权 GRANTED---授权  DINIED---拒绝
                } else {
                    return true;
                }
            case Manifest.permission.READ_EXTERNAL_STORAGE:
            case Manifest.permission.WRITE_EXTERNAL_STORAGE:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    boolean p = Environment.isExternalStorageManager();
                    return p;// 权限是否已经 授权 GRANTED---授权  DINIED---拒绝
                } else {
                    int r = ContextCompat.checkSelfPermission(activityWeakReference.get(), permissionName);
                    //Log.v(TAG, "[" + permissionName + "]权限:" + (r == PackageManager.PERMISSION_GRANTED ? "已授权" : "未授权"));
                    return (r == PackageManager.PERMISSION_GRANTED);// 权限是否已经 授权 GRANTED---授权  DINIED---拒绝
                }
            default:
                int r = ContextCompat.checkSelfPermission(activityWeakReference.get(), permissionName);
                //Log.v(TAG, "[" + permissionName + "]权限:" + (r == PackageManager.PERMISSION_GRANTED ? "已授权" : "未授权"));
                return (r == PackageManager.PERMISSION_GRANTED);// 权限是否已经 授权 GRANTED---授权  DINIED---拒绝
                /*Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(myIntent);*/
        }
        return true;
    }

    private static final Map<Integer, PermissionRequest> requestMap = new HashMap<>();

    public void requestPermission(PermissionRequest request) {
        requestMap.put(request.getRequestCode(), request);
        String permissionName = request.getCurrentPermission();
        if (TextUtils.isEmpty(permissionName)) {
            if (checkPermission(request.permissions.toArray(new String[request.permissions.size()]))) {
                request.granted();
            }else {
                request.denied();
            }
        } else {
            if (checkPermission(permissionName)) {//检查权限是否授权
                Log.e(TAG, "[" + permissionName + "]权限已授权");
                doRequestPermissionsResult(request);
            } else {//未授权
                permissionHandler.handleRequestPermission(activityWeakReference.get(), request);//自定义申请权限
            }
        }
        //requestPermissionImpl(request);
    }

    /**
     * 发起权限申请
     *
     * @param context
     * @param request
     */
    public void requestPermissionImpl(PermissionRequest request) {
        String permissionName = request.getCurrentPermission();
        Log.d(TAG, "用户确认后开始申请[" + permissionName + "]权限申请");
        if (checkPermission(permissionName)) {//自定义申请权限
            doRequestPermissionsResult(request);
            return;
        }

        String[] permissions = new String[]{permissionName};
        System.out.println("权限申请:" + request.getRequestIndex() + ",RequestCode:" + request.getRequestCode() + ",[" + permissionName + "]");
        switch (permissionName) {
            case Manifest.permission.REQUEST_INSTALL_PACKAGES://弹框提示用户手动打开
            case Manifest.permission.INSTALL_PACKAGES://弹框提示用户手动打开
            case Manifest.permission.SYSTEM_ALERT_WINDOW://System.out.println("悬浮窗权限");
            case Manifest.permission.PACKAGE_USAGE_STATS://查看网络访问状态
            case Manifest.permission.WRITE_SETTINGS:
            case Manifest.permission.BIND_ACCESSIBILITY_SERVICE:
            case Manifest.permission.MANAGE_EXTERNAL_STORAGE:
                QuickPermission2.getInstance().startPermissionActivity(activityWeakReference.get(), request);
                break;
            default:
                //if (context instanceof Activity) {
                ActivityCompat.requestPermissions(activityWeakReference.get(), permissions, request.getRequestCode());
                //} else {
//                    ContextCompat.checkSelfPermission(context, permissionName);
//                }
                break;
        }
    }

    /**
     * 权限请求结果
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    public void onRequestPermissionsResult(Activity context, int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        System.out.println("权限申请结果:" + requestCode + "," + String.join(",",permissions) + "," + grantResults);
        doPermissionResult(context,requestCode);
    }

    public void onActivityResult(Activity context, int requestCode, int resultCode, @Nullable Intent data) {
        System.out.println("权限申请结果1:" + requestCode + ",resultCode=" + resultCode );
        doPermissionResult(context,requestCode);
    }

    /**
     * 处理请求结果
     * @param requestCode
     */
    private void doPermissionResult(Activity context,int requestCode) {
        activityWeakReference = new WeakReference<>(context);
        if (requestMap.containsKey(requestCode)) {
            PermissionRequest request = requestMap.get(requestCode);
            System.out.println("权限申请结果3:" + requestCode + ",resultCode=" + String.join("",request.permissions) );
            requestMap.remove(requestCode);
            doRequestPermissionsResult(request);
        }
    }

    private void doRequestPermissionsResult(PermissionRequest request) {
        if (request != null) {
            String permissionName = request.getCurrentPermission();
            Log.i(TAG, "权限申请结果7：" + permissionName);
            if (TextUtils.isEmpty(permissionName)) {
                if (checkPermission(request.permissions.toArray(new String[request.permissions.size()]))) {
                    request.granted();
                }else {
                    request.denied();
                }
            } else {
                if (!checkPermission(permissionName)) {//权限未授权
                    boolean b = permissionHandler.handlePermissionDenial(activityWeakReference.get(), request);
                    Log.i(TAG, "请求被拒绝，是否强制重新发起申请1=" + b+","+String.join(",",request.permissions));
                    if (b) {//请求被拒绝，是否强制重新发起申请
                        Log.e(TAG, "请求被拒绝，强制重新发起申请2");
                        requestPermission(request);
                    }
                } else {//权限通过
                    request.next();
                    requestPermission(request);
                }
            }
        }
    }


    public void requestClipBoardPermission(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
            if (clipboard != null && clipboard.hasPrimaryClip()
                    && clipboard.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
                // 已经获取了粘贴板权限
            } else {
                // 未获取粘贴板权限
                setClipBoardPermission(context);
            }
        } else {
            // Android 版本低于 6.0，无需判断权限
        }
    }

    public static void setClipBoardPermission(Context context) {
        int MIUI_VERSION_CODE = 0;
        try {
            MIUI_VERSION_CODE = Integer.parseInt(Build.VERSION.INCREMENTAL);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }

        if (MIUI_VERSION_CODE >= 7) {
            // 小米 MIUI 7 及以上版本需要通过 Intent 来请求权限
            Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
            intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
            intent.putExtra("extra_pkgname", context.getPackageName());
            try {
                context.startActivity(intent);
            } catch (ActivityNotFoundException e) {
                e.printStackTrace();
            }
        } else {
            // 小米 MIUI 6 及以下版本可以直接跳转到应用详情页进行权限设置
            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            Uri uri = Uri.fromParts("package", context.getPackageName(), null);
            intent.setData(uri);
            try {
                context.startActivity(intent);
            } catch (ActivityNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    public static boolean checkAndEnableAccessibilityService(Context context) {
        AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        List<AccessibilityServiceInfo> serviceInfos = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
        //List<AccessibilityServiceInfo> installedAccessibilityServiceList = am.getInstalledAccessibilityServiceList();
        if (serviceInfos != null) {
            for (AccessibilityServiceInfo serviceInfo : serviceInfos) {
                if (serviceInfo.getId().startsWith(context.getPackageName())) {
                    //QdLog.e("无障碍服务已开启："+name);
                    return true;
                }
            }
        }
        return false;
    }


    /**
     * 启动新的 Activity 以引导用户手动授予权限。
     *
     * @param context      应用上下文
     * @param request      权限请求对象
     */
    public void startPermissionActivity(Context context, PermissionRequest request) {
        Intent intent = null;
        String permissionName = request.getCurrentPermission();//.getPermissionModelList().get(request.getIndex()).getName();

        Uri packageURI = Uri.parse("package:" + context.getPackageName());
        switch (permissionName) {
            case Manifest.permission.WRITE_SETTINGS:
                intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
                intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
                break;
            case Manifest.permission.PACKAGE_USAGE_STATS://查看网络访问状态
                intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
                break;
            case Manifest.permission.REQUEST_INSTALL_PACKAGES://弹框提示用户手动打开
            case Manifest.permission.INSTALL_PACKAGES://弹框提示用户手动打开
                intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                break;
            case Manifest.permission.SYSTEM_ALERT_WINDOW://悬浮窗权限
                intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                break;
            case Manifest.permission.BIND_ACCESSIBILITY_SERVICE://跳转系统自带界面 辅助功能界面
                intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
                //intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                packageURI = null;
                break;
            case Manifest.permission.MANAGE_EXTERNAL_STORAGE:
                intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                break;
        }
        if (packageURI != null) {
            intent.setData(packageURI);
        }
        if (context instanceof Activity) {
            ((Activity) context).startActivityForResult(intent, request.getRequestCode());//QuickPermission.REQUEST_PERMISS_SPECIAL_CODE);
        } else {
            intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
        permissionHandler.onStartPermissionActivity(context, request);
    }


    public void startAppDitailSettings(Context context, int requestCode) {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", context.getPackageName(), null);
        intent.setData(uri);
        ((Activity)context).startActivityForResult(intent, requestCode);
    }
}